Relación N:M a dos FK como clave primaria compuesta
Guía completa paso a paso para entender por qué en una relación muchos a muchos se utilizan las dos claves foráneas como clave primaria compuesta, cuándo usar una PK artificial y cómo diseñar correctamente tablas intermedias en SQL.
Bloque 1 · Concepto base
¿Qué es una relación N:M?
Una relación N:M (muchos a muchos) ocurre cuando:
Un registro de la tabla A puede relacionarse con muchos registros de la tabla B.
Y un registro de la tabla B puede relacionarse con muchos registros de la tabla A.
Ejemplo clásico
Entidad
Relación
Alumno
Puede estar en muchos cursos
Curso
Puede tener muchos alumnos
Esto NO puede representarse directamente en SQL con una sola FK.
Por eso aparece una tabla intermedia
Matricula
---------
id_alumno
id_curso
La tabla intermedia representa la RELACIÓN entre dos entidades.
Bloque 2 · Identidad real
¿Qué identifica realmente una fila?
La pregunta clave es:
¿Qué hace única una matrícula?
No es un número inventado.
Lo que realmente identifica la fila es:
Qué alumno.
En qué curso.
Por tanto
PRIMARY KEY (id_alumno, id_curso)
La combinación de ambas claves foráneas ya es única.
Eso significa que:
No necesitas otra clave artificial.
Evitas duplicados automáticamente.
El modelo es más lógico.
La PK compuesta representa la identidad REAL de la relación.
Bloque 3 · Problema de PK artificial
¿Qué ocurre si usas una PK artificial?
Muchas personas crean algo así:
CREATE TABLE matricula (
id_matricula INT PRIMARY KEY,
id_alumno INT,
id_curso INT
);
Problema
SQL solo controla que id_matricula no se repita.
Pero NO controla duplicados lógicos.
Ejemplo
1 | 14 | 3
2 | 14 | 3
Para SQL son filas distintas.
Pero en el mundo real:
El alumno 14 está repetido en el curso 3.
¿Cómo se arregla?
ALTER TABLE matricula
ADD CONSTRAINT uq_alumno_curso
UNIQUE(id_alumno, id_curso);
Al final acabas teniendo:
PK artificial.
UNIQUE adicional.
Dos índices.
Más complejidad.
Bloque 4 · PK compuesta correcta
Ejemplo correcto con PK compuesta
Tablas principales
CREATE TABLE alumno (
id_alumno INT PRIMARY KEY,
nombre VARCHAR(50)
);
CREATE TABLE curso (
id_curso INT PRIMARY KEY,
nombre VARCHAR(50)
);